#include "tvoc_co2_sensor.h"
#include "usart.h"
#include "stdio.h"
#include "string.h" 

#define TVOC_CO2_RX_BUFFER_SIZE 10 
#define TVOC_CO2_MODULE_ADDR_B1 0x2C
#define TVOC_CO2_MODULE_ADDR_B2 0xE4

TVOC_CO2_Data_t tvoc_co2_data;
static uint8_t tvoc_co2_rx_buffer[TVOC_CO2_RX_BUFFER_SIZE]; 

void TVOC_CO2_Init(void) {
    tvoc_co2_data.tvoc_high = 0;
    tvoc_co2_data.tvoc_low = 0;
    tvoc_co2_data.tvoc_mg_m3 = 0.0f;
    tvoc_co2_data.co2_high = 0;
    tvoc_co2_data.co2_low = 0;
    tvoc_co2_data.co2_mg_m3 = 0.0f;
    tvoc_co2_data.ch2o_high = 0;
    tvoc_co2_data.ch2o_low = 0;
    tvoc_co2_data.ch2o_mg_m3 = 0.0f;
    tvoc_co2_data.module_addr_b1 = 0;
    tvoc_co2_data.module_addr_b2 = 0;
    tvoc_co2_data.checksum = 0;
    tvoc_co2_data.calculated_checksum = 0;
    tvoc_co2_data.data_valid = 0;
}


HAL_StatusTypeDef TVOC_CO2_Read_Data(void) {
    HAL_StatusTypeDef status;
    uint8_t calculated_checksum = 0;

    printf("TVOC-CO2: Attempting to read data.\r\n");
    status = HAL_UART_Receive(&huart1, tvoc_co2_rx_buffer, TVOC_CO2_RX_BUFFER_SIZE, 100); // Blocking receive with 100ms timeout

    if (status == HAL_OK) {
        printf("TVOC-CO2: Raw data received: ");
        for(int i = 0; i < TVOC_CO2_RX_BUFFER_SIZE; i++) {
            printf("0x%02X ", tvoc_co2_rx_buffer[i]);
        }
        printf("\r\n");

        if (tvoc_co2_rx_buffer[1] != TVOC_CO2_MODULE_ADDR_B1 ||
            tvoc_co2_rx_buffer[2] != TVOC_CO2_MODULE_ADDR_B2) {
            tvoc_co2_data.data_valid = 0;
            printf("TVOC-CO2: Invalid module address. Got 0x%02X 0x%02X, Expected 0x%02X 0x%02X\r\n", 
                    tvoc_co2_rx_buffer[1], tvoc_co2_rx_buffer[2], 
                    TVOC_CO2_MODULE_ADDR_B1, TVOC_CO2_MODULE_ADDR_B2);
            return HAL_ERROR;
        }


        for (int i = 1; i < 9; i++) {
            calculated_checksum += tvoc_co2_rx_buffer[i];
        }


        if (calculated_checksum == tvoc_co2_rx_buffer[9]) {
            tvoc_co2_data.module_addr_b1 = tvoc_co2_rx_buffer[1];
            tvoc_co2_data.module_addr_b2 = tvoc_co2_rx_buffer[2];
            
            // TVOC data
            tvoc_co2_data.tvoc_high = tvoc_co2_rx_buffer[3];
            tvoc_co2_data.tvoc_low = tvoc_co2_rx_buffer[4];
            tvoc_co2_data.tvoc_mg_m3 = (float)(((uint16_t)tvoc_co2_data.tvoc_high << 8) | tvoc_co2_data.tvoc_low) * 0.001f;
            
            // CH2O data
            tvoc_co2_data.ch2o_high = tvoc_co2_rx_buffer[5];
            tvoc_co2_data.ch2o_low = tvoc_co2_rx_buffer[6];
            tvoc_co2_data.ch2o_mg_m3 = (float)(((uint16_t)tvoc_co2_data.ch2o_high << 8) | tvoc_co2_data.ch2o_low) * 0.001f;
            
            // CO2 data
            tvoc_co2_data.co2_high = tvoc_co2_rx_buffer[7];
            tvoc_co2_data.co2_low = tvoc_co2_rx_buffer[8];
            tvoc_co2_data.co2_mg_m3 = (float)(((uint16_t)tvoc_co2_data.co2_high << 8) | tvoc_co2_data.co2_low) * 0.001f;
            
            tvoc_co2_data.checksum = tvoc_co2_rx_buffer[9]; 
            tvoc_co2_data.calculated_checksum = calculated_checksum;
            tvoc_co2_data.data_valid = 1;

            printf("TVOC: %.3f, CH2O: %.3f, CO2: %.3f\r\n", 
                    tvoc_co2_data.tvoc_mg_m3, tvoc_co2_data.ch2o_mg_m3, tvoc_co2_data.co2_mg_m3);
            return HAL_OK;
        } else {
            tvoc_co2_data.data_valid = 0;
            printf("TVOC-CO2: Checksum mismatch. Calculated 0x%02X, Received 0x%02X\r\n", calculated_checksum, tvoc_co2_rx_buffer[9]);
            return HAL_ERROR;
        }
    } else if (status == HAL_TIMEOUT) {
        tvoc_co2_data.data_valid = 0;
        printf("TVOC-CO2: UART Receive timeout.\r\n");
        return HAL_TIMEOUT;
    } else {
        tvoc_co2_data.data_valid = 0;
        printf("TVOC-CO2: UART Receive error. Status: %d\r\n", status);
        return HAL_ERROR;
    }
}
